﻿/////////////////////////////////////////////////////////////////////////////////
//
// InstantCube
// - Automatically generates Analysis Services cubes
// (C) Copyright Johan Åhlén 2009
// 
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
// See the GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
//
// More info on InstantCube website: http://instantcube.codeplex.com
//
/////////////////////////////////////////////////////////////////////////////////


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Xml.Linq;

namespace AdvantIQ.InstantCube.Model
{
    public class TimeDimension : Dimension
    {
        public string TimeDimensionName { get; set; }

        private Project project;

        public TimeDimension(XElement srcNode, Project project)
            : base(project)
        {
            try
            {
                this.project = project;
                ID = "Time";

                TimeDimensionName = srcNode.Attribute("id").Value;
                DefaultMember = srcNode.Attribute("defaultMember").Value;

                Hierarchies = new Hierarchies(srcNode.Element("hierarchies"));
                var range = new TimeDimensionRange(srcNode);
                var parts = new TimeDimensionParts(srcNode.Element("timeParts"));

                InitAttributes(parts);
                InitValues(range, parts);

                InsertFieldNames = (from f in GetFields()
                                    where !f.IsReadonly
                                    select f.ID).ToArray();

                AddAttributeRelationships(srcNode.Element("attributeRelationships"));

                foreach (var attribute in Attributes.Values)
                {
                    attribute.Visible = Hierarchies.Count() == 0;
                }
            }
            catch (ModelErrorException ex)
            {
                throw new ModelErrorException(this, ex);
            }
            catch (Exception ex)
            {
                throw new ModelErrorException(this, ex.Message);
            }
        }

        public override string ToString()
        {
            return "TimeDimension";
        }

        private void InitAttributes(TimeDimensionParts dateParts)
        {
            Attributes = new Attributes(null, project);
            foreach (var datePart in dateParts)
            {
                var attribute = new Attribute(null, project) { ID = datePart.ID };
                var lst = new List<AttributePart>();
                lst.Add(new AttributePart(AttributePart.AttributePartType.Key, project.DefaultTypes.SurrogateKey, datePart.ID, project));
                lst.Add(new AttributePart(AttributePart.AttributePartType.Name, project.DefaultTypes.Name, datePart.ID, project));
                attribute.Parts = lst.ToArray();
                Attributes.Add(attribute.ID, attribute);
            }

            KeyAttribute = "Day";
        }

        private void InitValues(TimeDimensionRange range, TimeDimensionParts parts)
        {
            Values = new Values(null);
            for (DateTime date = range.StartDate; date <= range.EndDate; date = date.AddDays(1))
            {
                var lst = new List<string>();
                lst.Add(date.ToString("yyyyMMdd"));
                foreach (var part in parts)
                {
                    lst.Add(date.ToString(part.Key));
                    lst.Add(date.ToString(part.Name));
                }
                var row = new Row(lst);
                Values.Add(row);
            }
        }

        public override List<FieldInfo> GetFields()
        {
            var lst = new List<FieldInfo>();

            lst.Add(new FieldInfo("CalendarDate", 
                FieldType.Other, 
                "Date", 
                "NOT NULL"));
            foreach (var attribute in Attributes.Values)
            {
                foreach (var part in attribute.Parts)
                {
                    lst.Add(new FieldInfo(part.FieldName, 
                        FieldType.Attribute, 
                        part.FieldType, 
                        "NOT NULL" ));
                }
            }

            return lst;
        }

        public override string GetPrimaryKey()
        {
            return Attributes["Day"].Key.FieldName;
        }

        public override string GetKeyAttribute()
        {
            return "Day";
        }
    }
}
